package org.example;

import org.apache.commons.math3.distribution.NormalDistribution;
import tech.tablesaw.api.DoubleColumn;
import tech.tablesaw.api.Table;
import tech.tablesaw.plotly.Plot;
import tech.tablesaw.plotly.components.Axis;
import tech.tablesaw.plotly.components.Figure;
import tech.tablesaw.plotly.components.Layout;
import tech.tablesaw.plotly.components.Line;
import tech.tablesaw.plotly.traces.ScatterTrace;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;

public class IMRControlChart {

    public static void main(String[] args) throws Exception {
        double[] samples = Util.loadData();
        Figure[] charts = getCharts(samples);
        String XChart = Chart2Html.write(charts[0]);
        Files.write(Paths.get("XCharts.html"), XChart.getBytes());
        String MRChart = Chart2Html.write(charts[1]);
        Files.write(Paths.get("MRCharts.html"), MRChart.getBytes());
    }

    public static Figure[] getCharts(double[] samples) throws Exception {
//         生成50个随机数样本（正态分布，均值=10，标准差=2）

        // 计算移动极差（MR）
        double[] movingRanges = calculateMovingRanges(samples);

        // 创建Tablesaw数据表
        Table data = Table.create("Control Chart Data")
                .addColumns(
                        DoubleColumn.create("Index", range(1, samples.length + 1)),
                        DoubleColumn.create("Sample", samples),
                        DoubleColumn.create("MovingRange", padMovingRanges(movingRanges, samples.length))
                );

        // 计算控制限
        double avg = data.doubleColumn("Sample").mean();
        double avgMR = data.doubleColumn("MovingRange").mean();

        // I图控制限
        double iUCL = avg + 2.66 * avgMR;
        double iLCL = avg - 2.66 * avgMR;

        // MR图控制限
        double mrUCL = 3.267 * avgMR;
        double mrLCL = 0;

        // 添加控制限数据列
        data.addColumns(
                DoubleColumn.create("I_UCL", constantArray(iUCL, samples.length)),
                DoubleColumn.create("I_CL", constantArray(avg, samples.length)),
                DoubleColumn.create("I_LCL", constantArray(iLCL, samples.length)),
                DoubleColumn.create("MR_UCL", constantArray(mrUCL, samples.length)),
                DoubleColumn.create("MR_CL", constantArray(avgMR, samples.length)),
                DoubleColumn.create("MR_LCL", constantArray(mrLCL, samples.length))
        );

        // 绘制控制图
        return plotIMRChart(data);
    }

    // 计算移动极差（相邻两点的绝对差）
    private static double[] calculateMovingRanges(double[] data) {
        double[] ranges = new double[data.length - 1];
        for (int i = 1; i < data.length; i++) {
            ranges[i - 1] = Math.abs(data[i] - data[i - 1]);
        }
        return ranges;
    }

    // 填充MR数组（首项补NaN）
    private static double[] padMovingRanges(double[] mr, int targetLength) {
        double[] padded = new double[targetLength];
        Arrays.fill(padded, Double.NaN);
        System.arraycopy(mr, 0, padded, 1, mr.length);
        return padded;
    }

    // 生成连续整数序列
    private static double[] range(int start, int end) {
        double[] range = new double[end - start];
        for (int i = 0; i < range.length; i++) {
            range[i] = start + i;
        }
        return range;
    }

    // 生成常量数组
    private static double[] constantArray(double value, int length) {
        double[] array = new double[length];
        Arrays.fill(array, value);
        return array;
    }

    // 绘制I-MR控制图
    private static Figure[] plotIMRChart(Table data) throws Exception {
        Figure[] r= new Figure[2];
        // 1. I图 ========================================
        Layout iLayout = Layout.builder()
                .title("I Chart (Individual Values)")
                .xAxis(Axis.builder().title("Sample Index").build())
                .yAxis(Axis.builder().title("Value").build())
                .width(800)
                .height(400)
                .build();

        ScatterTrace sampleTrace = ScatterTrace.builder(
                        data.doubleColumn("Index"),
                        data.doubleColumn("Sample"))
                .name("Sample")
                .mode(ScatterTrace.Mode.LINE)
                .build();

        ScatterTrace uclTrace = ScatterTrace.builder(
                        data.doubleColumn("Index"),
                        data.doubleColumn("I_UCL"))
                .name("UCL")
                .mode(ScatterTrace.Mode.LINE)
                .line(Line.builder().color("red").dash(Line.Dash.DASH).width(1).build())
                .build();

        ScatterTrace clTrace = ScatterTrace.builder(
                        data.doubleColumn("Index"),
                        data.doubleColumn("I_CL"))
                .name("CL")
                .mode(ScatterTrace.Mode.LINE)
                .line(Line.builder().color("green").dash(Line.Dash.DASH).width(1).build())
                .build();

        ScatterTrace lclTrace = ScatterTrace.builder(
                        data.doubleColumn("Index"),
                        data.doubleColumn("I_LCL"))
                .name("LCL")
                .mode(ScatterTrace.Mode.LINE)
                .line(Line.builder().color("red").dash(Line.Dash.DASH).width(1).build())
                .build();

        Figure iChart = new Figure(iLayout, sampleTrace, uclTrace, clTrace, lclTrace);
        r[0]=iChart;
        // 2. MR图 ========================================
        Table mrData = data.dropWhere(data.doubleColumn("MovingRange").isMissing());
        Layout mrLayout = Layout.builder()
                .title("MR Chart (Moving Range)")
                .xAxis(Axis.builder().title("Sample Index").build())
                .yAxis(Axis.builder().title("Range").build())
                .width(800)
                .height(400)
                .build();

        ScatterTrace mrTrace = ScatterTrace.builder(
                        mrData.doubleColumn("Index"),
                        mrData.doubleColumn("MovingRange"))
                .name("Moving Range")
                .mode(ScatterTrace.Mode.LINE)
                .build();

        ScatterTrace mrUclTrace = ScatterTrace.builder(
                        mrData.doubleColumn("Index"),
                        mrData.doubleColumn("MR_UCL"))
                .name("UCL")
                .mode(ScatterTrace.Mode.LINE)
                .line(Line.builder().color("red").dash(Line.Dash.DASH).width(1).build())
                .build();

        ScatterTrace mrClTrace = ScatterTrace.builder(
                        mrData.doubleColumn("Index"),
                        mrData.doubleColumn("MR_CL"))
                .name("CL")
                .mode(ScatterTrace.Mode.LINE)
                .line(Line.builder().color("green").dash(Line.Dash.DASH).width(1).build())
                .build();

        ScatterTrace mrLclTrace = ScatterTrace.builder(
                        mrData.doubleColumn("Index"),
                        mrData.doubleColumn("MR_LCL"))
                .name("LCL")
                .mode(ScatterTrace.Mode.LINE)
                .line(Line.builder().color("red").dash(Line.Dash.DASH).width(1).build())
                .build();

        Figure mrChart = new Figure(mrLayout, mrTrace, mrUclTrace, mrClTrace, mrLclTrace);
        r[1] = mrChart;
        return r;
//         生成合并图表
//        String html = buildCombinedHtml(iChart, mrChart);
//        Files.write(Paths.get("ControlCharts.html"), html.getBytes());
    }


    private static String buildCombinedHtml(Figure iChart, Figure mrChart) {
//        Plot.show(iChart);
        return "<!DOCTYPE html>\n" +
                "<html>\n" +
                "<head>\n" +
                "    <title>I-MR Control Charts</title>\n" +
                "    <script src='https://cdn.plot.ly/plotly-latest.min.js'></script>\n" +
                "    <style>\n" +
                "        .chart-container { \n" +
                "            width: 90%; \n" +
                "            margin: 20px auto; \n" +
                "            border: 1px solid #eee;\n" +
                "            padding: 10px;\n" +
                "        }\n" +
                "        h2 { text-align: center; }\n" +
                "    </style>\n" +
                "</head>\n" +
                "<body>\n" +
                "    <div class='chart-container'>\n" +
                "        <h2>I Chart (Individual Values)</h2>\n" +
                "        <div id='iChart'></div>\n" +
                "    </div>\n" +
                "    <div class='chart-container'>\n" +
                "        <h2>MR Chart (Moving Range)</h2>\n" +
                "        <div id='mrChart'></div>\n" +
                "    </div>\n" +
                iChart.asJavascript("iChart") + "\n" +

                mrChart.asJavascript("mrChart") + "\n" +
                "</body>\n" +
                "</html>";
    }
}